"""
    Contains CRUDController, ItemTab and ItemActionsTab.
"""

import turbogears
from turbogears import validate, expose, widgets, database, identity, controllers, redirect
from mnemoply.controllers.containers import ModelObjectContainer
from mnemoply.controllers.lookup_new import LookupController
from mnemoply.widgets import column_item_view, fields_for, FieldGroup
from cherrypy._cperror import NotFound

class ItemTab(controllers.Controller):
    """
        Represent small tab lookup inside other controller.
    """

    params = ['title']
    title = "tab"

    def update_params(self, d):
        super(ItemTab, self).update_params(d)
        d['tab'] = self

    def display(self):
        return None, None

class ItemActionsTab(ItemTab):
    """
        Represent small tab lookup inside other controller with mass actions.
    """

    params = ['ma_class_name']

    title = "Actions tab"
    translated = [_("No records"), _("Select all"), _("Clear all")]
    template = "item_actions_tab"
    ma_class_name = None
    name = None

    def display(self):
        #TODO
        return self.ma_class_name, self.name

    def getRecords(self, obj):
        return []

    def getRecordTitle(self, record):
        return record.title

class ItemActionsTab1(ItemTab):
    """
        Represent small tab lookup inside other controller with mass actions.
    """

    title = "Actions tab"
    template = "item_actions_tab1"
    name = None
    fields = []
    obj_field = None
    model_object_child=None
    field_object_main=None
    def getRecords(self, obj):
        return []
    @expose()
    def delete_action(self, obj, _id):
        self.model_object_child.get(int(_id)).destroySelf()
        raise redirect("./")
    def add_action(self, obj, **kw):
        pass
    def get_add_form(self, obj=None):
        add_form = widgets.TableForm(
            fields=self.fields,
            submit_text=_("Add"),
            action='add_action',
        )
        return add_form
    def getRecordTitle(self, record):
        return record.title

class RestrictController(ModelObjectContainer, LookupController):
    form_widget_class = widgets.TableForm
    item_template = "genshi:mnemoply.templates.crud.item"
    view_fields = None
    model_object = None
    item_tabs = []
    item_tabs1 = []
    
    def __init__(self):
        ModelObjectContainer.__init__(self, self.model_object)
        if self.mysql_view_name is None or not self.mysql_view_name:
            self.mysql_view_name = self.model_object.sqlmeta.table+'_lookup'
        LookupController.__init__(self,
            columns=self.lookup_columns,
            mass_actions_class=self.model_object,
            title=self.model_object.model_title,
        )

        if not self.view_fields:
            self.view_fields = self.model_object.sqlmeta.columns.keys()

        assert len(self.view_fields) > 0
        if isinstance(self.view_fields[0], (str, unicode)):
            self.view_fields = [FieldGroup(fields=self.view_fields)]
        self.facets.extend(self.item_tabs)

        for item in self.item_tabs:
            item.controller = self



    def obj2item_view(self, obj):
        values = database.so_to_dict(obj)
        result = {}
        for k, v in values.items():
            if k == 'id':
                result[k] = (v, None)
            else:
                result[k] = (column_item_view(obj.sqlmeta.columns[k], v),
                             obj.sqlmeta.columns[k])
        return result

    def obj2edit_view(self, obj):
        return database.so_to_dict(obj)
    
    def hasShowAccess(self):
        return True

    @expose()
    def show(self, obj):
            # TODO 
        return dict(
            fields=self.obj2edit_view(obj),
            obj=obj,
            is_editable = self.hasEditAccess(),
            model_object=self.model_object,
            action='edit',
            action_text=_("Update"),
            local_menu=self.object_local_menu,
            controller=self,
            # from show
            view_fields=self.view_fields,
            values=self.obj2item_view(obj),
            tabs=self.item_tabs,
            tabs1=self.item_tabs1,
            tg_template=self.item_template,
        )
    show.expose_object = True
    
class CRUDController(RestrictController):
    """
        Based on FastData controller. Create view and edit form from model.
    """

    form_template = "genshi:mnemoply.templates.crud.form"
    add_fields = None
    edit_fields = None
    redirect_after_edit = "edit_req"

    def __init__(self):
        RestrictController.__init__(self)

        self.is_addable=self.is_editable=True
        if self.edit_fields is not None:
            self.is_editable = len(self.edit_fields)
            self.edit_fields = [FieldGroup(fields=self.edit_fields)]
        else:
            self.edit_fields = self.view_fields

        if self.add_fields is not None:
            self.is_addable = len(self.add_fields)
            self.add_fields = [FieldGroup(fields=self.add_fields)]
        else:
            self.add_fields = self.edit_fields

        self.add_widget = self.form_widget_class(
            fields=fields_for(self.model_object, self.add_fields))

        
        

    def _get_edit_fields(self, obj):
        return self.edit_fields

    def _get_add_form(self):
        return self.add_widget

    def _get_edit_form(self, obj=None):
        if obj is None:
            return self.form_widget_class(
                fields=fields_for(self.model_object, self.edit_fields))
        else:  # TODO: hack
            fs = self._get_edit_fields(obj)
            if len(fs) and type(fs[0]) == str:
                fs = [FieldGroup(fields=fs)]
            return self.form_widget_class(
                fields=fields_for(self.model_object, fs))

    def hasEditAccess(self):
        return identity.has_any_permission('dba',
                                           self.model_object.getModelName() + '/edit',
                                           self.model_object.getModelName() + '/all')\
            and self.is_editable 
                         
    def hasDeleteAccess(self):
        return identity.has_any_permission('dba',
                                           self.model_object.getModelName() + '/delete',
                                           self.model_object.getModelName() + '/edit')
    
    def hasAddAccess(self):
        return identity.has_any_permission('dba',
                                           self.model_object.getModelName() + '/add',
                                           self.model_object.getModelName() + '/edit')\
            and self.is_addable 
                         


    def defaultAddValues(self):
        return None

    @expose()
    def add_req(self):
        self.checkAddAccess()

        return dict(
            tg_template=self.form_template,
            obj=None,
            fields=self.defaultAddValues(),
            model_object=self.model_object,
            form=self.add_widget,
            action="add",
            action_text=_("Add"),
            local_menu=self.local_menu,
        )

    @validate(form=_get_add_form)
    @expose()
    def add(self, tg_errors=None, **data):
        self.checkAddAccess()

        if tg_errors:
            return self.add_req()

        data = self.before_update(data)
        obj = self.model_object(**data)

        link = ' link:%s:%d/' % (_('view'), obj.id)
        turbogears.flash(_('Record "%s" added!') % obj.title + link)
        raise turbogears.redirect("./add_req")


    @expose()
    def delete(self, obj):
        self.checkDeleteAccess()

        delete_form = widgets.TableForm(submit_text=_("Delete anyway"),
            action='destroyCascade')

        get_ref_names = lambda refs: ["%s: %s" % (obj.model_title, obj.title) for obj in refs]

        direct_references = reversed(get_ref_names(obj.findReferences()))
        all_references = reversed(get_ref_names(obj.findReferencesCascade()))

        if len(all_references) > 0:
            return dict(
                tg_template="genshi:mnemoply.templates.crud.delete_cant",
                direct_references=direct_references,
                all_references=all_references,
                delete_form=delete_form,
            )
        else:
            title = obj.title
            obj.destroySelf()
            turbogears.flash(_('Record "%s" deleted!') % title)
            raise turbogears.redirect("../")
    delete.expose_object = True

    @identity.require(identity.has_any_permission('dba', 'destroyCascade'))
    @expose()
    def destroyCascade(self, obj, **data):
        obj.destroyCascade()
        title = obj.title
        turbogears.flash(_('Record "%s" deleted!') % title)
        raise turbogears.redirect("../")
    destroyCascade.expose_object = True

    @expose()
    def edit_req(self, obj):
        print 'PPPPPPPPPP'
        print self.show
        return dict(
            fields=self.obj2edit_view(obj),
            model_object=self.model_object,
            obj=obj,
            form=self._get_edit_form(obj),
            is_editable = self.hasEditAccess(),
            action='edit',
            action_text=_("Update"),
            local_menu=self.object_local_menu,
            controller=self,
            tg_template="genshi:mnemoply.templates.crud.form_edit"
        )
    edit_req.expose_object = True

    def before_update(self, data):
        owner = identity.current.user.person
        return self.model_object.addOwnerToData(data, owner)

    def _update_kw(self, obj, kw):
        return kw

    def _delete_tg_errors(self, tg_errors):
        return tg_errors

    @validate(form=_get_edit_form)
    @expose()
    def edit(self, obj, tg_errors=None, **data):
        self.checkEditAccess()

        tg_errors = self._delete_tg_errors(tg_errors)

        if tg_errors:
            turbogears.flash(_("Check fields"))
            return self.edit_req(obj)
        data = self.before_update(data)
        data = self._update_kw(obj, data)
        obj.set(**data)
        turbogears.flash(_('Changes for "%s" saved!') % obj.title)
        raise turbogears.redirect(self.redirect_after_edit)

    edit.expose_object = True
